\subsection{System Architecture and Behavior (Stef{\'{a}}n Freyr)}
My primary focus was on the overall architecture of the system and implementation of behaviors
such as transitions and layouts. I also took a look at performance improvements to some extent.
\subsubsection{System Architecture}
A developer using pr3Da will mainly need to interact with the \texttt{Pr3daManager}
class. In the following paragraphs we describe the main components of the system.

\paragraph{The pluggable image loading mechanism} is responsible for retrieving pictures from an
external source. The API for a picture loading plugin is defined by the class
\texttt{Pr3daPlugin} which defines two functions: 

\begin{description}
\item \texttt{search(query)} which accepts a query string and returns a list of URLs for images 
matching the search criteria. It's up to the plugin implementation how to interpret the search 
string. For example, the filesystem plugin that we implemented matches the string against the 
filename on disk and allows wildcard characters.

\item \texttt{getLoader()} which returns a callable element that accepts a single argument which
is the URL of an image file to load. The callable must then return a \texttt{PNMImage} instance 
containing this image.
\end{description}

The idea here is that the callable loader function returned by \texttt{getLoader()} will know
how to handle the URLs returned by the search function of the corresponding plugin. When an 
image is constructed inside pr3Da it will do so by referencing the loader function which gets 
called only when needed (when the image is about to be displayed inside the virtual world).

Plugins are registered via the \texttt{registerPlugin(plugin)} function in \texttt{Pr3daManager}.
A \texttt{getPlugins()} function is also provided that lists all registered plugins and a
\texttt{search(query, plugins)} function delegates the supplied query to all plugins specified by 
the \texttt{plugins} list argument.

\paragraph{Search functionality.}
The return value of a call to \texttt{Pr3daManager.search(query, plugins)} is a list of 
tuples with each tuple consisting of 1) a reference to the plugin responsible for that match and 2) the 
URL of the matched image. The system requires each of these images to be encapsulated inside a
\texttt{Picture} instance. Furthermore, to display the \texttt{Picture} instances, they must be 
collected into a \texttt{Pr3daSet} instance. \texttt{Pr3daManager} provides a convenience function
to simplify this process. By sending the output of a call to the search function directly 
into the \texttt{createSet(purls)} function you get an instance of a \texttt{Pr3daSet} containing all 
matching images.

\paragraph{Layout and transitions for picture sets.}
Once a \texttt{Pr3daSet} has been created, it can be displayed in the virtual environment by calling
the \texttt{Pr3daManager.addSet(pset)} function. The way the set is displayed can be controlled to 
an extent. The \texttt{Pr3daSet} class defines a \texttt{setLayout(layout)} function that accepts
an instance of a layout management class. By setting a layout manager on the set before adding it to
the environment, you delegate the responsibility of arranging the pictures in the set to the specified
layout manager. The Layout API is defined by the \texttt{Pr3daLayout} class. The interface is a simple 
two step stateful process. Before any rendering is performed, the system calls the
\texttt{prepareLayout(pset)} function. The argument is the \texttt{Pr3daSet} that is to be displayed.
This function must calculate and store the locations of all images in the set, essentially preparing 
for the actual picture transitions to those locations.

The way that pictures are moved to their assigned locations is handled by an implementation of the
Transition API, defined by the \texttt{Pr3daTransition} class. A transition instance can be assigned 
to each layout by calling the \texttt{setTransition(transition)} function in \texttt{Pr3daLayout}. 
The transition API is very simple and stateless. Basically, when the layout is executed, the
\texttt{doTransition(np\_pos)} function is called. The argument is a list of tuples, each containing 
the Panda3D node path that should be moved and the new location for it. The functions only purpose is 
to tell Panda3D how to execute the transition. The pr3Da system comes with only one transition 
implementation that simply uses a \texttt{LerpPosInterval} to move the node path to the new position.

Originally, we had planned to implement a flocking behavior transition. As the deadline drew closer it
became apparent that we would not be able to implement this. However, we had done a bit of research
and found that there is a dominant algorithm that is used to implement this which is described in
\cite{boids}. The algorithm is very simple and should not be hard to implement. The only uncertainty
is how Panda3D would support this implementation since individuals in the flock (the pictures in our 
case) need to get constant updates on their direction and velocity during the duration of the transition.
One of the reasons this got put off was the uncertainty that such flocking behavior would turn out to
be aesthetically pleasing. These transitions must take place in a short period of time in order not to
become annoying for the user. After some thoughts we concluded that flocking behavior in a transition
that takes only a second would probably look chaotic and disturbing.

We had also planned to implement a layout algorithm that arranged pictures in a cloud in a visually 
pleasing way while still maintaining some element of randomness. After some research on this topic we 
found a family of algorithms that are very commonly used in graph drawing and are referred to as 
force directed algorithms. A prominent algorithm of that family is the Kamada-Kawai algorithm described 
in \cite{fdla}. Adding a pr3Da layout manager that implements this algorithm would be a trivial task. 
Only lack of time prevented us from implementing it.

\subsubsection{Lazy-loading mipmapping.}
We did not put much effort into performance considerations since we are firm believers in the phrase 
{\em ``Premature optimization is the root of all evil!''} (Donald Knuth). When we started the project, we
contemplated implementing what we called a lazy-loading mipmap to ``optimize'' the performance of the
system. Our idea was that mipmapping would speed things up when images were being displayed as very small 
objects far away since we would only load the smallest version of the image in that scenario. One problem
with that idea is that our environment just doesn't work that way. Pictures are never loaded to be displayed
far away from the start. Every time a picture is loaded into the environment, it is loaded into the current 
set which is closest to the user and thus, needs to have a decent level of detail. There are potential uses 
for this technique though. For example if the picture being loaded is very large, it would be beneficial to 
load a smaller version of it to avoid loading details that are of no use. Another problem with our logic 
about mipmaps was that the mipmap technique is not actually intended to optimize loading time of the texture 
as was our intent. Rather, it is intended to optimize rendering speed and quality for constantly changing 
and moving textures. In fact, mipmapping incurs a 33\% overhead in texture memory usage. From this it became
apparent that we would not spend our effort implementing this seemingly premature optimization.